function MODEL=Setup_MODEL(PP,SS)


%% Setup Variables
%--------------------------------------------------------------------------
% Variable Declarification
%--------------------------------------------------------------------------
% State: Exogenous  (State_Ex)
ExState     =   struct('Eta_Z',DsgeVarClass('Eta_Z',0,'State_Ex','Lin'),...
                       'Eta_Z_N',DsgeVarClass('Eta_Z_N',0,'State_Ex','Lin'), ...
                       'Eta_Z_H',DsgeVarClass('Eta_Z_H',0,'State_Ex','Lin'), ...
                       'Eta_M_dom',DsgeVarClass('Eta_M_dom',0,'State_Ex','Lin'), ...
                       'Eta_M_ext',DsgeVarClass('Eta_M_ext',0,'State_Ex','Lin'), ...
                       'Eta_Y_H',DsgeVarClass('Eta_Y_H',0,'State_Ex','Lin') ...
                       );
% State: Endogenous (State_En)
EnState     =   struct('Lag_p_N',DsgeVarClass('Lag_p_N',SS.p_N,'State_En','Log'), ...
                       'Lag_p_T',DsgeVarClass('Lag_p_T',SS.p_T,'State_En','Log'), ...
                       'Lag_p_H',DsgeVarClass('Lag_p_H',SS.p_H,'State_En','Log'), ...
                       'Lag_p_F',DsgeVarClass('Lag_p_F',SS.p_F,'State_En','Log'), ...
                       'Lag_B',DsgeVarClass('Lag_B',SS.B,'State_En','Lin'), ...
                       'Lag_GB',DsgeVarClass('Lag_GB',SS.GB,'State_En','Lin'), ...
                       'Lag_ir',DsgeVarClass('Lag_ir',SS.ir,'State_En','Lin') ...
                       );
% Control: NK (Control)
NKControl   =   struct('C_N',DsgeVarClass('C_N',SS.C_N,'Control','Log'), ...
                       'C_T',DsgeVarClass('C_T',SS.C_T,'Control','Log'), ...
                       'C_H',DsgeVarClass('C_H',SS.C_H,'Control','Log'), ...
                       'C_F',DsgeVarClass('C_F',SS.C_F,'Control','Log'), ...
                       'p_N',DsgeVarClass('p_N',SS.p_N,'Control','Log'), ...
                       'p_T',DsgeVarClass('p_T',SS.p_T,'Control','Log'), ...
                       'p_H',DsgeVarClass('p_H',SS.p_H,'Control','Log'), ...
                       'p_F',DsgeVarClass('p_F',SS.p_F,'Control','Log'), ...
                       'Pir_N',DsgeVarClass('Pir_N',SS.Pir_N,'Control','Lin'), ...
                       'Pir_H',DsgeVarClass('Pir_H',SS.Pir_H,'Control','Lin'), ...
                       'Pir_F',DsgeVarClass('Pir_F',SS.Pir_F,'Control','Lin'), ...
                       'Y_N',DsgeVarClass('Y_N',SS.Y_N,'Control','Log'), ...
                       'Y_H',DsgeVarClass('Y_H',SS.Y_H,'Control','Log'), ...
                       'N_N',DsgeVarClass('N_N',SS.N_N,'Control','Log'), ...
                       'N_H',DsgeVarClass('N_H',SS.N_H,'Control','Log'), ...
                       'w',DsgeVarClass('w',SS.w,'Control','Log'), ...
                       'mc_N',DsgeVarClass('mc_N',SS.mc_N,'Control','Log'), ...
                       'mc_H',DsgeVarClass('mc_H',SS.mc_H,'Control','Log'), ...
                       'PAC_N',DsgeVarClass('PAC_N',SS.PAC_N,'Control','Lin'), ...
                       'PAC_H',DsgeVarClass('PAC_H',SS.PAC_H,'Control','Lin'), ...
                       'Profit_N',DsgeVarClass('Profit_N',SS.Profit_N,'Control','Lin'), ...
                       'Profit_H',DsgeVarClass('Profit_H',SS.Profit_H,'Control','Lin'), ...
                       'Y',DsgeVarClass('Y',SS.Y,'Control','Log'), ...
                       'PAC',DsgeVarClass('PAC',SS.PAC,'Control','Lin'), ...
                       'Profit',DsgeVarClass('Profit',SS.Profit,'Control','Lin'), ...
                       'Pir',DsgeVarClass('Pir',SS.Pir,'Control','Lin'), ...
                       'ir',DsgeVarClass('ir',SS.ir,'Control','Lin'), ...
                       'T',DsgeVarClass('T',SS.T,'Control','Lin'), ...
                       'B',DsgeVarClass('B',SS.B,'Control','Lin'), ...
                       'GB',DsgeVarClass('GB',SS.GB,'Control','Lin'), ...
                       'TAU',DsgeVarClass('TAU',SS.TAU,'Control','Lin'), ...
                       'dE',DsgeVarClass('dE',SS.dE,'Control','Lin'), ...
                       'ir_s',DsgeVarClass('ir_s',SS.ir_s,'Control','Lin'), ...
                       'Pir_H_s',DsgeVarClass('Pir_H_s',SS.Pir_H_s,'Control','Lin'), ...
                       'Pir_F_s',DsgeVarClass('Pir_F_s',SS.Pir_F_s,'Control','Lin'), ...
                       'ir_dom',DsgeVarClass('ir_dom',SS.ir_dom,'Control','Lin'), ...
                       'ir_ext',DsgeVarClass('ir_ext',SS.ir_ext,'Control','Lin'), ...
                       'rr_dom',DsgeVarClass('rr_dom',SS.rr_dom,'Control','Lin'), ...
                       'rr_ext',DsgeVarClass('rr_ext',SS.rr_ext,'Control','Lin') ...
                       );
% Control: HH (Control)
HHControl   =   struct('C',DsgeVarClass('C',SS.C,'Control','Log'), ...
                       'L',DsgeVarClass('L',SS.L,'Control','Log') );
% Auxiliary Variables: Aux
AuxVar      =   struct();
% Variable Collections: VAR
VAR         =   struct();
VAR_Cell    =   {ExState,EnState,NKControl,HHControl,AuxVar};
for ii=1:length(VAR_Cell)
    TempFields  =   fieldnames(VAR_Cell{ii});
    for jj=1:length(TempFields)
        TempVar     =   TempFields{jj};
        TempVarp    =   [TempVar,'p'];
        VAR.(TempVar) ...
                    =   VAR_Cell{ii}.(TempVar);
        VAR.(TempVarp) ...
                    =   VAR_Cell{ii}.(TempVar);
        VAR.(TempVarp).Name ...
                    =   [VAR.(TempVarp).Name,'p'];
    end
end

%--------------------------------------------------------------------------
% Variable Categories: State (XX), Control (YY) and Shocks (SH)
%--------------------------------------------------------------------------
% XX
XX              =   struct();
XX.VarList      =   cat(1,fieldnames(ExState),fieldnames(EnState));
XX.LocIdx       =   struct();
XX.VarNum       =   length(XX.VarList);
XX.Dim          =   0;
TempStartIdx    =   0;
for ii=1:XX.VarNum
    TempVar         =   XX.VarList{ii};
    TempDim         =   VAR.(TempVar).Dim;
    XX.Dim          =   XX.Dim+TempDim;
    XX.LocIdx.(TempVar) ...
                    =   TempStartIdx+(1:TempDim)';
    TempStartIdx    =   TempStartIdx+TempDim;
end
% YY
YY              =   struct();
YY.VarList      =   cat(1,fieldnames(HHControl),fieldnames(NKControl));
YY.LocIdx       =   struct();
YY.VarNum       =   length(YY.VarList);
YY.Dim          =   0;
TempStartIdx    =   0;
for ii=1:YY.VarNum
    TempVar         =   YY.VarList{ii};
    TempDim         =   VAR.(TempVar).Dim;
    YY.Dim          =   YY.Dim+TempDim;
    YY.LocIdx.(TempVar) ...
                    =   TempStartIdx+(1:TempDim)';
    TempStartIdx    =   TempStartIdx+TempDim;
end
% SH
SH              =   struct();
SH.VarList      =   fieldnames(ExState);
SH.LocIdx       =   struct();
SH.Dim          =   0;
SH.VarNum       =   length(SH.VarList);
TempStartIdx    =   0;
for ii=1:SH.VarNum
    TempVar         =   SH.VarList{ii};
    SH.VarList{ii}  =   ['Eps_',TempVar];
    TempDim         =   VAR.(TempVar).Dim;
    SH.Dim          =   SH.Dim+TempDim;
    SH.LocIdx.(SH.VarList{ii}) ...
                    =   TempStartIdx+(1:TempDim)';
    TempStartIdx    =   TempStartIdx+TempDim;
end

%--------------------------------------------------------------------------
% Duplicate the Variables Information in XXp, YYp
%--------------------------------------------------------------------------
% XXp
XXp             =   struct();
XXp.VarNum      =   XX.VarNum;
XXp.Dim         =   XX.Dim;
XXp.VarList     =   cell(XXp.VarNum,1);
for ii=1:XX.VarNum
    TempVar         =   XX.VarList{ii};
    TempVarp        =   [TempVar,'p'];
    XXp.VarList{ii} =   TempVarp;
    XXp.LocIdx.(TempVarp) ...
                    =   XX.LocIdx.(TempVar);
end
% YYp
YYp             =   struct();
YYp.VarNum      =   YY.VarNum;
YYp.Dim         =   YY.Dim;
YYp.VarList     =   cell(YYp.VarNum,1);
for ii=1:YY.VarNum
    TempVar         =   YY.VarList{ii};
    TempVarp        =   [TempVar,'p'];
    YYp.VarList{ii} =   TempVarp;
    YYp.LocIdx.(TempVarp) ...
                    =   YY.LocIdx.(TempVar);
end

VarBlock        =   struct('SH',SH,'XX',XX,'YY',YY,'XXp',XXp,'YYp',YYp);

%% Setup Equations
%--------------------------------------------------------------------------
% Variable Declarification (In and Out sides cannot include same variables)
%--------------------------------------------------------------------------
% HH Block
arg_List        =   {'In','Out'};
arg.In          =   {'Lag_B','Cp','Pirp','dEp', ...
                     'Pir','dE','T','Profit','TAU','ir_dom','ir_ext','w'}';
arg.Out         =   {'B','C','L'}';

Equ             =   struct();
for ii=1:length(arg_List)
    IO              =   arg_List{ii};
    TempNum         =   length(arg.(IO));
    TempVarFlag     =   false(TempNum,1);
    Equ.Dim.(IO)    =   0;
    Equ.LocIdx.(IO) =   struct();
    TempStartIdx    =   0;
    for jj=1:TempNum
        TempVar         =   arg.(IO){jj};
        if ischar(TempVar)
            TempVarFlag(jj) =   1;
            Equ.Dim.(IO)    =   Equ.Dim.(IO)+VAR.(TempVar).Dim;
            Equ.LocIdx.(IO).(TempVar) ...
                            =   TempStartIdx+(1:VAR.(TempVar).Dim)';
            TempStartIdx    =   TempStartIdx+VAR.(TempVar).Dim;
        elseif isvector(TempVar)
            Equ.Dim.(IO)    =   Equ.Dim.(IO)+length(TempVar);
            TempStartIdx    =   TempStartIdx+length(TempVar);
        else
            error('Unknown input/output type');
        end
    end
    Equ.Var.(IO)    =   arg.(IO)(TempVarFlag);
    Equ.Num.(IO)    =   sum(TempVarFlag);
end

Equ_HH          =   Equ;
% NK Block
arg_List        =   {'In','Out'};
arg.In          =   {'Eta_Z','Eta_Zp','Eta_Z_N','Eta_Z_Np','Eta_Z_H','Eta_Z_Hp','Eta_M_dom','Eta_M_domp',...
                     'Eta_M_ext','Eta_M_extp','Eta_Y_H','Eta_Y_Hp','N_N','N_H','w','mc_N',...
                     'mc_H','Y_N','Y_H','Profit_N','Profit_H','PAC_N','PAC_H','Y_Np',...
                     'Y_Hp','L','C_N','C_T','C_H','C_F','p_T','p_N',...
                     'p_H','p_F','Pir','Pirp','Pir_N','Pir_H','Pir_F','Lag_p_T',...
                     'Lag_p_N','Lag_p_H','Lag_p_F','Lag_p_Tp','Lag_p_Np','Lag_p_Hp','Lag_p_Fp','p_Np',...
                     'p_Hp','Pir_Np','Pir_Hp','ir_dom','ir_ext','rr_dom','rr_ext','ir',...
                     'TAU','B','T','ir_s','Pir_H_s','Pir_F_s','dE','dEp',...
                     'Y','C','Profit','PAC','GB','Lag_GB','Lag_GBp','Lag_B',...
                     'Lag_Bp','Lag_ir','Lag_irp'
                     }';
arg.Out         =   {zeros(51,1)}';


Equ             =   struct();
for ii=1:length(arg_List)
    IO              =   arg_List{ii};
    TempNum         =   length(arg.(IO));
    TempVarFlag     =   false(TempNum,1);
    Equ.Dim.(IO)    =   0;
    Equ.LocIdx.(IO) =   struct();
    TempStartIdx    =   0;
    for jj=1:TempNum
        TempVar         =   arg.(IO){jj};
        if ischar(TempVar)
            TempVarFlag(jj) =   1;
            Equ.Dim.(IO)    =   Equ.Dim.(IO)+VAR.(TempVar).Dim;
            Equ.LocIdx.(IO).(TempVar) ...
                            =   TempStartIdx+(1:VAR.(TempVar).Dim)';
            TempStartIdx    =   TempStartIdx+VAR.(TempVar).Dim;
        elseif isvector(TempVar)
            Equ.Dim.(IO)    =   Equ.Dim.(IO)+length(TempVar);
            TempStartIdx    =   TempStartIdx+length(TempVar);
        else
            error('Unknown input/output type');
        end
        
        
    end
    Equ.Var.(IO)    =   arg.(IO)(TempVarFlag);
    Equ.Num.(IO)    =   sum(TempVarFlag);
end

Equ_NK          =   Equ;

%--------------------------------------------------------------------------
% Equation Collection
%--------------------------------------------------------------------------
EquBlock        =   struct('HH',Equ_HH,'NK',Equ_NK);

%% Setup Model
MODEL           =   struct('VAR',VAR,'VarBlock',VarBlock,'EquBlock',EquBlock);
%--------------------------------------------------------------------------
% Model Information
%--------------------------------------------------------------------------
% Variables
VarDim          =   VarBlock.XX.Dim+VarBlock.YY.Dim;
% Equations
EquList         =   fieldnames(EquBlock);
EquNum          =   length(EquList);
EquDim          =   0;
for ii=1:EquNum
    EquDim          =   EquDim+EquBlock.(EquList{ii}).Dim.Out;
end

if EquDim~=VarDim
    error(['Dimension Inconsistency: ', ...
           num2str(VarDim), ' Variables ',',with ',num2str(EquDim),' Equations']);
end

MODEL.Info      =   struct('Dim',EquDim,'EquList',{EquList});
